로딩 중이에요... 🐣
[코담]
웹개발·실전 프로젝트·AI까지, 파이썬·장고의 모든것을 담아낸 강의와 개발 노트
23 좋아요 기능 백엔드 API 구현 | ✅ 편저: 코담 운영자
23강 - 좋아요 기능: 백엔드 API 구현
기능 - API✨ 이번 강의 목표
- Django 모델에서 좋아요 기능을 위한 필드 구성
- Django REST Framework(GenericAPIView)를 사용한 API 구현
- 좋아요 추가 및 취소 기능 구현 (POST 요청)
1. 모델 설정
django_instagram/posts/models.py
# 게시글
class Post(TimeStampedModel):
author = models.ForeignKey(
user_models.User,
null=True, # DB에서 null 허용
on_delete=models.CASCADE,
related_name='post_author',
verbose_name=_("작성자")
)
image = models.ImageField(_("이미지"), upload_to="posts/", blank=False)
caption = models.TextField(_("내용"), blank=False)
image_likes = models.ManyToManyField(
user_models.User,
blank=True,
related_name='post_image_likes',
verbose_name=_("좋아요")
)
def __str__(self):
return f"{self.author} : {self.caption}"
class Meta:
verbose_name = _("게시물")
verbose_name_plural = _("게시물들")
ordering = ['-created_at']
image_likes
: 게시글에 좋아요를 누른 유저 목록을 저장하는 M2M 필드__str__
: admin 등에서 객체 표시를 명확히 하기 위해 사용
2. URL 패턴
django_instagram/posts/api/urls.py
from django.urls import path
from .views import PostListView, PostLikeView
from . import views
app_name = "posts_api"
urlpatterns = [
path("posts/", PostListView.as_view(), name="posts-list"),
path("posts/list", views.posts_list_view, name="posts-list"),
path("posts/<int:post_id>/post_like/", PostLikeView.as_view(), name="post_like"),
]
3. DRF 기반 좋아요 API View
django_instagram/posts/api/views.py
from django.shortcuts import get_object_or_404
from django_instagram.users.models import User as user_model
from rest_framework.response import Response
from rest_framework import status, generics, permissions
from django_instagram.posts.models import Post
from .serializers import PostSerializer, CommentFormSerializer, UserSerializer
from django.db.models import Q
from django_instagram.posts.forms import CommentForm
from django_instagram.posts import models
from django.http import JsonResponse
from rest_framework.decorators import api_view
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
# DRF 방식: 게시글 리스트
class PostListView(generics.ListAPIView):
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
user = get_object_or_404(user_model, pk=self.request.user.id)
following = user.following.all()
return Post.objects.filter(Q(author__in=following) | Q(author=user)).order_by('-created_at')
def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True, context={'request': request})
login_user_serializer = UserSerializer(request.user, context={'request': request})
return Response({"posts": serializer.data, "loginUser": login_user_serializer.data}, status=status.HTTP_200_OK)
# FBV 방식: 게시글 리스트
@api_view(['GET'])
def posts_list_view(request):
if request.method == 'GET':
user = get_object_or_404(user_model, pk=request.user.id)
following = user.following.all()
followed_posts = models.Post.objects.filter(Q(author__in=following) | Q(author=user)).order_by('-created_at')
serializer = PostSerializer(followed_posts, many=True, context={'request': request})
login_user_serializer = UserSerializer(request.user, context={'request': request})
return JsonResponse({"posts": serializer.data, "loginUser": login_user_serializer.data}, status=200)
# DRF: 좋아요 추가 및 취소
class PostLikeView(generics.GenericAPIView):
permission_classes = [permissions.IsAuthenticated]
def post(self, request, post_id):
post = get_object_or_404(models.Post, pk=post_id)
user = request.user
if post.image_likes.filter(pk=user.pk).exists():
post.image_likes.remove(user)
is_added = False
else:
post.image_likes.add(user)
is_added = True
return Response({
"success": True,
"message": "like" if is_added else "dislike",
"like_count": post.image_likes.count()
}, status=status.HTTP_200_OK)
✅ 주요 설명
- GenericAPIView를 상속받아 POST 메서드만 오버라이드
request.user
가 이미 좋아요를 눌렀는지 확인 후 add/remove 처리- 응답으로 성공 여부, 상태 메시지, 좋아요 수 반환
4. FBV 방식의 대안 구현 (선택사항)
# FBV: 좋아요 추가 및 취소
@require_POST
@login_required
def post_like(request, post_id):
post = get_object_or_404(models.Post, pk=post_id)
try:
if post.image_likes.filter(pk=request.user.pk).exists():
post.image_likes.remove(request.user)
is_added = False
else:
post.image_likes.add(request.user)
is_added = True
return JsonResponse({
"success": True,
"message": "like" if is_added else "dislike",
"like_count": post.image_likes.count()
}, status=200)
except Exception as e:
return JsonResponse({"success": False, "message": "오류가 발생했습니다.", "error": str(e)}, status=500)
- FBV(Function Based View) 방식에서도 동일한 로직 구현 가능
- Django 데코레이터 기반 (
@login_required
,@require_POST
)
✅ 정리
항목 | 설명 |
---|---|
모델 필드 | image_likes (ManyToManyField)로 좋아요 구현 |
API View | PostLikeView : POST 요청으로 add/remove 처리 |
응답 구조 | { success, message, like_count } |
추가 설명 | DRF 또는 FBV 중 하나 선택해 구현 가능 |
👉 다음 강의에서는 Ajax 호출 시 CSRF 토큰과 함께 이 API를 연동합니다.